package com.sam.spring.chapter5.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.DeclareParents;
import org.aspectj.lang.annotation.Pointcut;

import com.sam.spring.chapter5.service.IIntroductionService;

@Aspect
public class HelloWorldAspectAnnotation {
	@Pointcut(value = "execution(* com.sam..*.sayAdvisorBefore(..)) && args(param)", argNames = "param")
	public void beforePointcut(String param) {
	}

	@Before(value = "beforePointcut(param)", argNames = "param")
	public void beforeAdvice(String param) {
		System.out.println("===========before advice param:" + param);
	}

	@AfterReturning(value = "execution(* com.sam..*.sayAfterReturning(..))", returning = "retVal", argNames = "retVal")
	public void afterReturningAdvice(Object retVal) {
		System.out
				.println("===========after returning advice retVal:" + retVal);
	}

	@AfterThrowing(value = "execution(* com.sam..*.sayAfterThrowing(..))", throwing = "exception", argNames = "exception")
	public void afterThrowingAdvice(Exception exception) {
		System.out.println("===========after throwing advice exception:"
				+ exception);
	}

	@After(value = "execution(* com.sam..*.sayAfterFinally(..))")
	public void afterFinallyAdvice() {
		System.out.println("===========after finally advice");
	}

	@Around(value = "execution(* com.sam..*.sayAround(..))")
	public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
		System.out.println("===========around before advice");
		Object retVal = pjp.proceed(new Object[] { "replaced..." });
		System.out.println("===========around after advice");
		return retVal;
	}

	@DeclareParents(value = "com.sam..*.IHelloWorldService+", defaultImpl = com.sam.spring.chapter5.service.impl.IntroductiondService.class)
	private IIntroductionService introductionService;
}
